package com.quanzhi.hyperscan.label;

import com.quanzhi.hyperscan.wrapper.*;
import com.quanzhi.hyperscan.wrapper.Match;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import java.io.IOException;
import java.io.InputStream;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
public class RegexMatcher {

    LabelRegex labelRegex=null;
    LinkedList<Expression> expressions = new LinkedList<Expression>();
    Database db =null;
    Scanner scanner = null;

    static EnumSet<ExpressionFlag> parseFlag(String flags)
    {
        EnumSet expressionFlags = EnumSet.noneOf(ExpressionFlag.class);
        for(int i=0;i<flags.length();i++)
        {
            switch(flags.charAt(i)){
                case 'i':
                    expressionFlags.add(ExpressionFlag.CASELESS);
                    break;
                case 's':
                    expressionFlags.add(ExpressionFlag.DOTALL);
                    break;
                case 'm':
                    expressionFlags.add(ExpressionFlag.MULTILINE);
                    break;
                case 'H':
                    expressionFlags.add(ExpressionFlag.SINGLEMATCH);
                    break;
                case 'V':
                    expressionFlags.add(ExpressionFlag.ALLOWEMPTY);
                    break;
                case '8':
                    expressionFlags.add(ExpressionFlag.UTF8);
                    break;
                case 'W':
                    expressionFlags.add(ExpressionFlag.UCP);
                    break;
                case 'P':
                    expressionFlags.add(ExpressionFlag.PREFILTER);
                    break;
                case 'L':
                    expressionFlags.add(ExpressionFlag.SOM_LEFTMOST);
                    break;
                case 'C':
                    expressionFlags.add(ExpressionFlag.COMBINATION);
                    break;
                case 'Q':
                    expressionFlags.add(ExpressionFlag.QUIET);
                    break;
                default:
                    System.out.println("doesn't contain the target flag,please check");

            }
        }
        return expressionFlags;

    }

    public RegexMatcher(){

        Yaml yaml = new Yaml(new Constructor(LabelRegex.class));

        InputStream inputStream=this.getClass().getClassLoader().getResourceAsStream("rule.yaml");
        labelRegex = yaml.load(inputStream);
    }

    public Boolean init() throws CompileErrorException, IOException {
        if(db != null)
            db.close();
        if(expressions.size() > 0)
            expressions.clear();

        for(int i=0;i<labelRegex.exprList.size();i++) {
            expressions.add(new Expression(labelRegex.exprList.get(i).regex,parseFlag(labelRegex.exprList.get(i).flag),
                    new RegexContext(labelRegex.exprList.get(i).name,labelRegex.exprList.get(i).id)));
        }
        db=Database.compile(expressions);
        scanner = new Scanner();
        scanner.allocScratch(db);

        return true;
    }

    public Boolean init(List<String> labels) throws IOException, CompileErrorException {
        if(db != null)
            db.close();
        if(expressions.size() > 0)
            expressions.clear();

        if(null == labels && labels.isEmpty())
        {
            System.out.println("labels is null,no labels input");
            return false;
        }
        //compare cared tag with supported labels
        for(int j=0;j<labels.size();j++) {
            String label = labels.get(j).toLowerCase();
            for (int i = 0; i < labelRegex.exprList.size(); i++)
            {
                if(label.equals(labelRegex.exprList.get(i).name.toLowerCase()))
                {
                    expressions.add(new Expression(labelRegex.exprList.get(i).regex, parseFlag(labelRegex.exprList.get(i).flag),
                            new RegexContext(labelRegex.exprList.get(i).name, labelRegex.exprList.get(i).id)));
                }
            }
        }
        db=Database.compile(expressions);
        scanner = new Scanner();
        scanner.allocScratch(db);

        return true;

    }

    public List<Match>  scan(String input)
    {
        if(db == null) {
            System.out.println("db init failed,please check init func.");
            return null;
        }

        List<Match> matches = scanner.scan(db,input);
        return matches;

    }

    public static void main(String[] args) {
        RegexMatcher regexMatcher = new RegexMatcher();
        System.out.println(regexMatcher.labelRegex.exprList.size());
    }



}
